package com.pcbly.web.components.utils.fileupload;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.log4j.Logger;

import com.pcbly.web.Constants;



/**
 * 上传Session管理器
 * @author cleverpig
 *
 */
@SuppressWarnings("unchecked")
public class UploadSessionManager {
	private static UploadSessionManager instance;
	private static Logger logger=Logger.getLogger(UploadSessionManager.class);
	
	static {
		instance = new UploadSessionManager();
	}
	//定时器
	private Timer timer;
	//session集合
	private Map sessions = Collections.synchronizedMap(new HashMap());
	
	public UploadSessionManager(){
	}
	
	/**
	 * 获取uploadSession
	 * @param uSessionId
	 * @return
	 */
	public UploadSessionImpl getUploadSession(String uSessionId){
		Logger innerLogger=Logger.getLogger(FileUploadStatusBeanManager.class);
		//如果已经存在，则重新激活此session
		if (hasSession(uSessionId)){
			UploadSessionImpl uSession=(UploadSessionImpl)getSession(uSessionId);
			uSession.reActive();
			return uSession;
		}
		//否则建立新的FUS Bean和session
		else{
			UploadSessionImpl uSession=new UploadSessionImpl(createSessionId());
			addSession(uSession);
			innerLogger.debug("没有发现uploadSession["+uSessionId+"]，新建UploadSession["+uSession.getId()+"]");
			return uSession;
		}
	}
	
	/**
	 * 添加uploadSession
	 * @param uSession
	 */
	public void addOrUpdateUploadSession(
			UploadSession uSession){
		addSession(uSession);
	}
	/**
	 * 返回上传会话中当前激活的FUS
	 * @param uSessionId
	 * @return
	 */
	public FileUploadStatus getActiveFUSBean(String uSessionId){
		return getUploadSession(uSessionId).getActiveFUSBean();
	}
	/**
	 * 返回上传会话中当前激活的FUS列表
	 * @param uSessionId
	 * @return
	 */
	public FileUploadStatusList getFUSBeanList(String uSessionId){
		return getUploadSession(uSessionId).getFUSBeanList();
	}
	/**
	 * session是否存在
	 * @param id
	 * @return
	 */
	public boolean hasSession(String id) {
		return sessions.containsKey(id);
	}
	/**
	 * 新建session id
	 * @return
	 */
	public String createSessionId() {
		String id = null;
		while (true) {
			id = Utils.randomName(Constants.SESSION_ID_SIZE);
			if (!hasSession(id)) {
				break;
			}
		}
		return id;
	}
	/**
	 * 获得管理器实例 
	 * @return
	 */
	public static UploadSessionManager getInstance() {
		return instance;
	}
	/**
	 * 使用session id获取session
	 * @param anId
	 * @return
	 */
	public UploadSession getSession(String anId) {
		return (UploadSession) sessions.get(anId);
	}
	/**
	 * 添加session,如果已经存在，则覆盖
	 * @param session
	 */
	public void addSession(UploadSession session) {
		if (sessions.containsKey(session.getId())){
			logger.info("session["+session.getId()+"]被更新");
		}
		else{
			logger.info("session["+session.getId()+"]被添加");
		}
		sessions.put(session.getId(), session);
		
	}
	/**
	 * 删除session
	 * @param session
	 * @return 返回被删除的session
	 */
	public UploadSession removeSession(UploadSession session) {
		UploadSession delSession = (UploadSession) sessions.remove(session.getId());
		if (delSession != null) {
			logger.info("session["+delSession.getId()+"]被删除");
		}
		return delSession;
	}
	/**
	 * 获得session集合的容量
	 * @return
	 */
	public int getSessionsCapability(){
		return sessions.size();
	}
	/**
	 * 启动管理器
	 */
	public void start() {
		if (timer != null) {
			stop();
		}
		timer = new Timer(false);
		timer.schedule(new AgingTimerTask(), Constants.TIMER_INTERVAL_MILLIS, Constants.TIMER_INTERVAL_MILLIS);
		logger.info("管理器启动中...周期=" + Constants.TIMER_INTERVAL_MILLIS + "ms");
	}
	/**
	 * 停止管理器
	 */
	public void stop() {
		if (timer != null) {
			timer.cancel();
			timer = null;
		}
		sessions.clear();
		logger.info("stopped");
	}
	
	/**
	 * 衰老定时器task
	 * @author cleverpig
	 *
	 */
	private class AgingTimerTask extends TimerTask {
		private long lastRun = System.currentTimeMillis();

		public void run() {
			long now = System.currentTimeMillis();
			long delta = now - lastRun;
			lastRun = now;

			UploadSession nextSession = null;
			UploadSession[] sessionsArray =new UploadSession[0];
			
			synchronized(sessionsArray){
				sessionsArray=(UploadSession[]) sessions.values().toArray(sessionsArray);
				for (int i = 0; i < sessionsArray.length; i++) {
					nextSession = sessionsArray[i];
					if (nextSession == null) {
						break;
					}
					try {
						nextSession.age(delta);
						if (nextSession.isExpired()) {
							logger.info("Session expired: " + nextSession);
							nextSession.stop();
						}
					} catch(Exception ex) {
						logger.warn("Error in timer task : " + ex.getMessage());
						ex.printStackTrace();
					}
				}
			}
		}
	}
}
